home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 332_01 / polish.c < prev    next >
C/C++ Source or Header  |  1990-03-28  |  7KB  |  309 lines

  1. /*----------------------------------------------------*- Fundamental -*-
  2.  
  3. Facility:        polish
  4.  
  5. File:            polish.c
  6.  
  7. Associated files:    - (none)
  8.  
  9. Description:        This is the RPN calculator taken from the
  10.             C Manual by Kernighan & Ritchie.  It's an
  11.             excellent example of stack implementation.
  12.  
  13. Notes:            Some changes has been made to the code to
  14.             make it more portable.
  15.  
  16. Author:            H. Moran (?)
  17.  
  18. Editor:            Anders Thulin
  19.             Rydsvagen 288
  20.             S-582 50 Linkoping
  21.             SWEDEN
  22.  
  23. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  24.  
  25. Edit history :
  26.  
  27. Vers  Ed   Date        By                Comments
  28. ----  ---  ----------  ----------------  -------------------------------
  29.  1.0    0  19xx-xx-xx  H. Moran (?) 
  30.  1.1    1  1988-12-21  Anders Thulin     General cleanup (original did
  31.                              not compile under K&R)
  32.  
  33. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  34.  
  35.  
  36. /*---  Configuration:  ----------------------------------------------
  37.  
  38. System configuration options:
  39. =============================
  40.  
  41.   ANSI        ANSI C
  42.   BSD        BSD Unix, SunOS 3.5
  43.   SV2        AT&T UNIX System V.2
  44.   XPG3        X/Open Portability Guide, ed. 3
  45.  
  46. If you have an ANSI C conformant compiler, define ANSI. If not,
  47. choose the definition that matches your setup best.
  48.  
  49.  
  50. Program configuration options:
  51. ==============================
  52.  
  53. Parameter    Original
  54. name         value    Comment
  55.  
  56. MAXOP         20        Max nr of chars in a number
  57. MAXVAL      100        Max size of stack
  58.  
  59. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  60.  
  61. #define    ANSI        1
  62. #define    BSD        0
  63. #define    SV2        0
  64. #define    XPG3        0
  65.  
  66. #define MAXOP    20
  67. #define MAXVAL 100
  68.  
  69. /*- End of configurations - - - - - - - - - - - - - - - - - - - - - - - - */
  70.  
  71. #if ANSI
  72. # include <ctype.h>
  73. # include <stdio.h>
  74. # include <stdlib.h>
  75. #endif
  76.  
  77. #if BSD
  78. # include <ctype.h>
  79. # include <stdio.h>
  80.   extern int atoi();
  81. # define EXIT_SUCCESS    0
  82. #endif
  83.  
  84. #if SV2
  85. # include <ctype.h>
  86. # include <stdio.h>
  87.   extern int atoi();
  88. # define EXIT_SUCCESS    0
  89. #endif
  90.  
  91. #if XPG3
  92. # include <ctype.h>
  93. # include <stdio.h>
  94. # include <stdlib.h>
  95. #endif
  96.  
  97. /*----------------------------------------------------------------------
  98.   Local definitions and variables:
  99. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  100.  
  101. #define NUMBER '0'
  102. #define TOOBIG '9'
  103.  
  104. static long val[MAXVAL];        /* Stack    */
  105. static int  stkpntr = 0;        /* Points to first empty element in stack */
  106.  
  107. /*----------------------------------------------------------------------
  108.   Local functions:
  109. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  110.  
  111. #if __STDC__ != 0
  112.  static void clear(void);
  113.  static int  getop(char *s, int lim);
  114.  static long pop(void);
  115.  static long push(long f);
  116. #else
  117.  static void clear();
  118.  static int  getop();
  119.  static long pop();
  120.  static long push();
  121. #endif
  122.  
  123.  
  124. /*----------------------------------------------------------------------
  125.  
  126. Routine:    clear
  127.  
  128. Description:    empty the stack
  129.  
  130. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  131.  
  132. static void clear ()
  133. {
  134.   stkpntr = 0;
  135. }
  136.  
  137. /*----------------------------------------------------------------------
  138.  
  139. Routine:    getop
  140.  
  141. Description:    Returns the next operand/operator from stdin
  142.  
  143.         An operand is any (unsigned) number. The separate
  144.         characters are stored in 's', and the value NUMBER
  145.         is returned.
  146.  
  147.         An operator is everything that is not a number or
  148.         a space.  The operator character is returned as
  149.         value.
  150.  
  151. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  152.  
  153. static int getop(s, lim)
  154. char s[];        /* character buffer */
  155. int lim;        /* size of character buffer */
  156. {
  157.   int i,c;
  158.  
  159.   /*  1.  Skip leading spaces:    */
  160.  
  161.   while (isspace(c = getchar()))
  162.     ;
  163.  
  164.   /*  2.  If not a number, then an operator char (or EOF):    */
  165.  
  166.   if (!isdigit(c)) {
  167.     return(c);
  168.   }
  169.  
  170.   /*  3.  Collect a number into s:    */
  171.  
  172.   s[0] = c;
  173.  
  174.   for (i = 1; isdigit(c = getchar()); i++) {
  175.     if (i < lim) {
  176.       s[i] = c;
  177.     }
  178.   }
  179.  
  180.   if (i < lim) {
  181.     ungetc(c, stdin);
  182.     s[i] = '\0';
  183.     return(NUMBER);
  184.   } else {             /* buffer overflow */
  185.     while (c != '\n') {        /* skip to eoln        */
  186.       c = getchar();
  187.     }
  188.     s[lim-1] = '\0';
  189.     return (TOOBIG);
  190.   }
  191. }
  192.  
  193. /*----------------------------------------------------------------------
  194.  
  195. Routine:    main
  196.  
  197. Description:    main program
  198.  
  199. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  200.  
  201. int main()
  202. {
  203.   int  type;        /* type of operand/operator from getop()    */
  204.   long op2;        /* temporary operand storage */
  205.   char s[MAXOP];    /* number buffer */
  206.  
  207.   stkpntr = 0;
  208.  
  209.   puts("polish -- reverse polish calculator");
  210.  
  211.   while ((type = getop(s,MAXOP)) != EOF) {
  212.     switch (type)  {
  213.  
  214.       default:
  215.     printf("  Unknown command %c\n", type);
  216.     break;
  217.  
  218.       case NUMBER:
  219.         (void)push(atoi(s));
  220.     break;
  221.  
  222.       case '+':
  223.         (void)push(pop() + pop());
  224.         break;
  225.  
  226.       case '*':
  227.     (void)push(pop() * pop());
  228.     break;
  229.  
  230.       case '-':
  231.     op2 = pop();
  232.     (void)push(pop() - op2);
  233.     break;
  234.  
  235.       case '/':
  236.     op2 = pop();
  237.     if (op2 != 0) {
  238.         (void)push(pop() / op2);
  239.     } else {
  240.         printf("Zero divisor popped\n");
  241.     }
  242.     break;
  243.  
  244.       case '=':
  245.     printf("        %d\n", push(pop()));
  246.     break;
  247.  
  248.       case 'c':
  249.     clear();
  250.     break;
  251.  
  252.       case TOOBIG:
  253.     printf("%.20s ... is too long\n", s);
  254.     break;
  255.  
  256.     }
  257.   }
  258.  
  259.   return EXIT_SUCCESS;        /* Never reached */
  260. }
  261.  
  262. /*----------------------------------------------------------------------
  263.  
  264. Routine:    pop
  265.  
  266. Description:    pop a value of the stack and return it as value
  267.  
  268.         If the stack is empty, print an error message,
  269.         clear the stack (to ensure that stackpointer is 0)
  270.         and return a 0.
  271.  
  272. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  273.  
  274. static long pop ()
  275. {
  276.   if (stkpntr > 0) {
  277.     return (val[--stkpntr]);
  278.   } else {
  279.     printf("Error: stack empty\n");
  280.     clear ();
  281.     return(0);
  282.   }
  283. }
  284.  
  285. /*----------------------------------------------------------------------
  286.  
  287. Routine:    push
  288.  
  289. Description:    push the argument onto the stack, and return it
  290.         as value.
  291.  
  292.         If the stack overflows, print an error message,
  293.         clear the stack, and return 0.
  294.  
  295. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  296.  
  297. static long push(f)
  298. long f;
  299. {
  300.   if (stkpntr < MAXVAL) {
  301.     return(val[stkpntr++] = f);
  302.   } else {
  303.     printf("Error: stack full\n");
  304.     clear();
  305.     return (0);
  306.   }
  307. }
  308.  
  309.